﻿using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Quickly.Identity.Policies;
using Quickly.Identity.Services.Manage;
using Quickly.Identity.Services.Manage.Roles;

namespace Quickly.Identity.API.Endpoints;

public static class RolesManageEndpoints
{
    public static IEndpointRouteBuilder MapRoleManageEndpoints<TRole>(this IEndpointRouteBuilder endpoints)
        where TRole : class
    {
        ArgumentNullException.ThrowIfNull(endpoints, nameof(endpoints));

        var routeGroup = endpoints.MapGroup("")
            .WithOpenApi()
            .WithTags("RoleManage");

        routeGroup.MapPost("/list",
            async ([FromBody] QueryRolesCommand command,
                   [FromServices] IQueryableRoleStore<TRole> queryableRoleStore,
                   CancellationToken cancellationToken) =>
            {
                return await QueryRoles.ExecuteAsync<TRole>(command, queryableRoleStore, cancellationToken);
            }).WithName("QueryRoles");

        routeGroup.MapPost("/detail",
            async ([FromBody] LoadRoleDetailCommand command,
                [FromServices] IRoleStore<TRole> roleStore,
                CancellationToken cancellationToken) =>
            {
                return await LoadRoleDetail.ExecuteAsync<TRole>(command, roleStore, cancellationToken);
            }).WithName("LoadRoleDetail");

        routeGroup.MapPost("/create",
            async (
                CreateRoleCommand command,
                RoleManager<AppRole> roleManager,
                CancellationToken cancellationToken) =>
        {
            return await CreateRole.ExecuteAsync(command, roleManager, cancellationToken);
        }).WithName("CreateRole");

        routeGroup.MapPost("/delete/{id}", async (string id, IRoleStore<AppRole> roleStore, CancellationToken cancellationToken) =>
        {
            cancellationToken.ThrowIfCancellationRequested();
            var role = await roleStore.FindByIdAsync(id, cancellationToken);
            if (role != null)
            {
                role.Deleted = true;
                role.LastModifiedTime = DateTimeOffset.UtcNow;

                await roleStore.UpdateAsync(role, cancellationToken);

                return IdentityResult.Success;
            }
            return IdentityResult.Failed(new IdentityError
            {
                Code = "NotExistsRole",
                Description = "要删除的角色不存在"
            });
        }).WithName("DeleteRole");

        routeGroup.MapPost("/recovery/{id}", async (string id, IRoleStore<AppRole> roleStore, CancellationToken cancellationToken) =>
        {
            cancellationToken.ThrowIfCancellationRequested();
            var role = await roleStore.FindByIdAsync(id, cancellationToken);
            if (role != null)
            {
                role.Deleted = false;
                role.LastModifiedTime = DateTimeOffset.UtcNow;

                await roleStore.UpdateAsync(role, cancellationToken);

                return IdentityResult.Success;
            }
            return IdentityResult.Failed(new IdentityError
            {
                Code = "NotExistsRole",
                Description = "要恢复的角色不存在"
            });
        }).WithName("RecoveryRole");

        return routeGroup;
    }
}
